package com.example.p2pinvest.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * @author h2tc01
 * @version 1.0.0
 * 2022/8/11
 * 自定义流式布局
 */
public class FlowLayout extends ViewGroup {

    public FlowLayout(Context context) {
        this(context, null);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    //重写的目的:给每个子视图指定显示的位置
    private List<List<View>> allViews = new ArrayList<>(); //每一行子视图的集合构成的集合
    private List<Integer> allHeights = new ArrayList<>(); //每一行高度构成的集合

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //1.给两个集合添加元素

        //每一行的宽高值
        int lineWidth = 0;
        int lineHeight = 0;

        //获取布局的宽度
        int width = this.getMeasuredWidth();

        //提供一个集合保存一行childView
        List<View> lineViewList = new ArrayList<>();

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);

            //获取子视图的宽高边距
            int childHeight = childView.getMeasuredHeight();
            int childWidth = childView.getMeasuredWidth();

            MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();

            if (lineWidth + childWidth + params.leftMargin + params.rightMargin <= width) {
                //不换行
                lineViewList.add(childView);
                lineWidth += childWidth + params.leftMargin + params.rightMargin;
                lineHeight = Math.max(lineHeight, childHeight + params.topMargin + params.bottomMargin);
            } else {
                //要换行

                //将上一行的子视图集合放入总视图集合
                allViews.add(lineViewList);
                //记录高度
                allHeights.add(lineHeight);

                //上一行的宽度和高度
                lineWidth = childWidth + params.leftMargin + params.rightMargin;
                lineHeight = childHeight + params.topMargin + params.bottomMargin;

                //下一行的子视图是一个新的集合
                lineViewList = new ArrayList<>();
                //添加下一行的第一个子视图
                lineViewList.add(childView);
            }

            if (i == childCount - 1) {
                //做结尾处理

                //将上一行的子视图集合放入总视图集合
                allViews.add(lineViewList);
                //记录高度
                allHeights.add(lineHeight);
            }
        }

        Log.e("TAG", "allView.size = " + allViews.size());
        Log.e("TAG", "allHeight.size = " + allHeights.size());

        //2.给每个子视图去定位
        int x = 0;
        int y = 0;
        for (int i = 0; i < allViews.size(); i++) {
            List<View> lineViews = allViews.get(i);
            for (int j = 0; j < lineViews.size(); j++) {
                View childView = lineViews.get(j);

                //测量子视图的宽高
                int childHeight = childView.getMeasuredHeight();
                int childWidth = childView.getMeasuredWidth();
                //获取子视图的边距参数
                MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();

                int left = x + params.leftMargin;  //左坐标为x轴最大值+自身左边距
                int top = y + params.topMargin;  //顶点坐标为y轴最大值 + 自身上边距
                int right = left + childWidth;  //右左边为左坐标值+自身宽度
                int bottom = top + childHeight;  //底坐标为顶点坐标 + 自身高度

                childView.layout(left, top, right, bottom);

                x += childWidth + params.leftMargin + params.rightMargin;  //每一行的x轴最大值: 子视图宽度+左右边距
            }
            //换行
            y += allHeights.get(i);  //高度累加
            x = 0;  //x轴长度重置
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取设置的宽高的模式和具体的值   wrap_content为至多模式   math_parent或自定义尺寸为精确模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //精确模式下的宽高
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        //如果用户使用的是至多模式,那么使用如下两个变量去计算真实的宽高值
        int width = 0;
        int height = 0;

        //每一行的宽高
        int lineWidth = 0;
        int lineHeight = 0;

        //获取子视图
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View chileView = getChildAt(i);

            //只有调用了如下方法才能计算子视图的宽高
            measureChild(chileView, widthMeasureSpec, heightMeasureSpec);

            //获取子视图的宽高
            int childWidth = chileView.getMeasuredWidth();
            int childHeight = chileView.getMeasuredHeight();

            //要想保证可以获取子视图的边距参数对象,必须重写generateLayoutParams()
            MarginLayoutParams params = (MarginLayoutParams) chileView.getLayoutParams();
            if (lineWidth + childWidth + params.leftMargin + params.rightMargin <= widthSize) {
                //计算 每行的现在宽度 + 要添加子视图的宽度  + 子视图本身的左边距 + 子视图本身的右边距
                //小于等于父视图宽度则不换行
                lineWidth += childWidth + params.leftMargin + params.rightMargin;
                lineHeight = Math.max(lineHeight, childHeight + params.topMargin + params.bottomMargin);

            } else {
                //换行
                width = Math.max(width, lineWidth);
                height += lineHeight;

                //重置,新一行的宽高就是第一个视图的宽高+左右边距
                lineWidth = childWidth + params.leftMargin + params.rightMargin;
                lineHeight = childHeight + params.topMargin + params.bottomMargin;
            }
            //最后一个元素
            if (i == childCount - 1) {
                width = Math.max(width, lineWidth);
                height += lineHeight;
            }
        }

        Log.e("TAG", "widthSize: " + widthSize + "|| heightSize: " + heightSize);
        Log.e("TAG", "width: " + width + "|| height: " + height);

        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width,
                heightMode == MeasureSpec.EXACTLY ? heightSize : height);

    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }
}
